package blackeagle.ems.entities;

import blackeagle.ems.BlackEagleEMS;
import blackeagle.ems.Logger;
import blackeagle.ems.dal.DataClass;
import blackeagle.ems.dal.DataField;
import blackeagle.ems.dal.DataList;
import blackeagle.ems.dal.DataRecord;
import blackeagle.ems.dal.MethodType;
import java.util.ArrayList;
import java.util.HashMap;
import se.oru.informatik.InformatikDB;
import se.oru.informatik.InformatikException;
import se.oru.informatik.StringHelper;

/**
 * A class representing an employee
 */
@DataClass(dataName="EMPLOYEE")
public class Employee extends DataRecord<Employee> {
    private Integer id, departmentId;
    private String firstname, surname, ssn;
    
    /**
     * The default 0-parameter constructor.
     */
    public Employee(){}  
    
    /**
     * A static class containing read-only fields with column names.
     */
    public static class Columns{
        public static final String DepartmentId = "departmentid";
        public static final String FirstName = "firstname";
        public static final String Id = "id";
        public static final String SSN = "ssn";
        public static final String Surname = "surname";
        
        private Columns(){}
    }

    /**
     * Gets the department to which this Employee is assigned.
     * @return A department if one can be successfully loaded; otherwise <code>null</code>.
     */
    public Department getDepartment(){
        Department dept = new Department();
        dept.load(this.departmentId);
        
        return (dept.isNew()?null:dept);
    }
    
    /**
     * Sets the department to which this Employee is assigned.
     * @param dept The department to which this employee will be assigned.
     */
    public void setDepartment(Department dept){
        Integer deptId = dept.getId();
        this.setDepartmentId(deptId);
    }
    
    /**
     * Gets the department id of this employee
     * @return the departmentId
     */
    @DataField(fieldName="departmentid",methodType=MethodType.Getter)
    public Integer getDepartmentId() {
        return departmentId;
    }

    /**
     * Sets the department id of this employee
     * @param departmentId the departmentId to set
     */
    @DataField(fieldName="departmentid",methodType=MethodType.Setter)
    public void setDepartmentId(Integer departmentId) {
        this.departmentId = departmentId;
            this._isDirty=true;
    }

    /**
     * Gets the first name of this employee
     * @return the first name
     */
    @DataField(fieldName="firstname",methodType=MethodType.Getter)
    public String getFirstname() {
        return firstname;
    }

    /**
     * Sets the first name of this employee
     * @param firstname the first name to set
     */
    @DataField(fieldName="firstname",methodType=MethodType.Setter)
    public void setFirstname(String firstname) {
        this.firstname = firstname;
        this._isDirty=true;
    }
    
    /**
     * Gets the id of this employee
     * @return the id
     */
    @DataField(fieldName="id", methodType=MethodType.Getter, isPrimary=true, autoIncrement=true)
    public Integer getId(){
        return this.id;
    }
    
    /**
     * Sets the id of this employee
     * @param value the id to set
     */
    @DataField(fieldName="id", methodType=MethodType.Setter, isPrimary=true, autoIncrement=true)
    public void setId(Integer value){
        if(value>0){
            this.id=value;
            this._isDirty=true;
        }        
    }

    /**
     * Gets the surname of this employee
     * @return the surname
     */
    @DataField(fieldName="surname",methodType=MethodType.Getter)
    public String getSurname() {
        return surname;
    }

    /**
     * Sets the surname of this employee
     * @param surname the surname to set
     */
    @DataField(fieldName="surname",methodType=MethodType.Setter)
    public void setSurname(String surname) {
        this.surname = surname;
        this._isDirty=true;
    }

    /**
     * Gets the Social Security Number (SSN) of this employee.
     * @return the SSN
     */
    @DataField(fieldName="ssn",methodType=MethodType.Getter)
    public String getSSN() {
        return ssn;
    }

    /**
     * Sets the Social Security Number (SSN) of this employee.
     * @param ssn the SSN to set
     */
    @DataField(fieldName="ssn",methodType=MethodType.Setter)
    public void setSSN(String ssn) {
        this.ssn = ssn;
        this._isDirty=true;
    }
    
    /**
     * Loads all the specialities of this Employee
     * @return the domains.
     */
    public DomainCollection getSpecialities(){
        DomainCollection dc = new DomainCollection();
        
        InformatikDB iDB = null;
        
        try{
            iDB = new InformatikDB(BlackEagleEMS.connectionString);
        }catch(InformatikException e){
            Logger.log(e.getMessage());
            return dc;
        }
        
        String query = StringHelper.sprintf("SELECT D.* FROM \"DOMAIN\" AS D INNER JOIN DOMAINSPECIALIST AS DS ON(D.ID=DS.DOMAINID) WHERE DS.EMPLOYEEID='#'", this.id);
        ArrayList<HashMap<String,String>> result = null;
        
        try{
            result = iDB.fetchRows(query);
        }catch(InformatikException e){
            Logger.log(e.getMessage());
            return dc;
        }
        
        dc.loadData(result);
        
        return dc;
    }
    
    /**
     * Checks if the Employee is assigned to a given domain as a specialist and returns the level that he or she is at.
     * @param domain The domain
     * @return -1 if the Employee is not assigned to that domain as a specialist; otherwise the level.
     */    
    public Integer getSpecialityLevel(Domain domain){
        InformatikDB iDB = null;
        try{
            iDB = new InformatikDB(BlackEagleEMS.connectionString);
        }catch(InformatikException ex){
            return -1;
        }
        
        String query = StringHelper.sprintf("SELECT \"LEVEL\" FROM DOMAINSPECIALIST WHERE domainid = '#' AND employeeid = '#'", new Object[] { domain.getId(), this.id });
        String result = null;
        
        try{
            result = iDB.fetchSingle(query);
        }catch(InformatikException ex){
            return -1;
        }
        
        Integer retval = -1;
        
        try{
            retval = Integer.parseInt(result);
        }catch(Exception ex){}
        
        return retval;
    }
    
    /**
     * Attempts to fetch all the subprojects to which this employee is assigned as a specialist.
     * @return 
     */
    public SubprojectCollection getSubprojects(){
        SubprojectCollection sc = new SubprojectCollection();
        
        InformatikDB iDB=null;
        try{
            iDB=new InformatikDB(BlackEagleEMS.connectionString);
        }catch(InformatikException e){
            return sc;
        }
        
        ArrayList<HashMap<String,String>> rows=null;
        try{
            rows=iDB.fetchRows(StringHelper.sprintf("SELECT S.* FROM SUBPROJECT AS S INNER JOIN SUBPROJECTSPECIALIST AS SS ON(S.ID=SS.SUBPROJECTID) WHERE SS.EMPLOYEEID='#'",this.id));
        }catch(InformatikException e){
            return sc;
        }
        
        sc.loadData(rows);
        
        return sc;
    }
    
    @Override
    public String toString(){
        return StringHelper.sprintf("# # (#)", this.firstname, this.surname, this.ssn);
    }
    
    @Override
    public boolean equals(Object object){
        if(object instanceof Employee){
            Employee e = (Employee)object;
            
            return (this.id==e.id);
        }
        
        return false;
    }
}
